﻿using System.Threading;
using System.Web;
using EnetaMvc.Infrastructure;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using System.Diagnostics;

namespace EnetaMvc.Data.NHibernate
{
    public class NHSession : IMapperSession
    {
        private static ISessionFactory _sessionFactory;
        private static Configuration _configuration;
        private ISession _currentSession;

        private const string SessionKey = "NH_SESSION";

        internal ISession GetCurrentSession()
        {
            if (_sessionFactory == null)
                InitSessionFactory();

            if (HttpContext.Current != null)
                return GetWebSession();

            return GetNewSession();
        }
        
        private ISession GetWebSession()
        {
            var session = HttpContext.Current.Items[SessionKey] as ISession;
            if (session != null)
                return session;

            session = _sessionFactory.OpenSession();

            HttpContext.Current.Items[SessionKey] = session;
            return session;
        }

        public static void CreateDbSchema()
        {
            if (_configuration == null)
                InitSessionFactory();
            
            var export = new SchemaExport(_configuration);
            export.Drop(false, true);
            export.Create(false, true);
        }

        private ISession GetNewSession()
        {
            if (_currentSession == null)
            {
                _currentSession = _sessionFactory.OpenSession();
            }
            return _currentSession;
        }

        private static void InitSessionFactory(string connectionString = "")
        {
            _configuration = new Configuration();
            _configuration.Configure(); 

            if (!string.IsNullOrEmpty(connectionString))
            {
                _configuration.SetProperty("connection.connection_string", connectionString);

            }
            
            _configuration.AddAssembly(typeof(NHSession).Assembly);

            _sessionFactory = _configuration.BuildSessionFactory();
        }

        public void SwitchToConnection(string connectionString)
        {
            if (HttpContext.Current != null)
            {
                var webSession = GetWebSession();
                webSession.Dispose();
                HttpContext.Current.Items.Remove(SessionKey);
            }

            if (_currentSession != null)
            {
                _currentSession.Dispose();
                _currentSession = null;
            }

            InitSessionFactory(connectionString);
        }
    }
}
